﻿using System;
using System.Security.Cryptography;
using System.IO;

namespace mmCrypt
{
    public class AesCrypt
    {
        private readonly byte[] _mKey = { 123, 217, 19, 11, 24, 26, 85, 45, 114, 184, 27, 162, 37, 112, 222, 209, 241, 24, 175, 144, 173, 53, 196, 29, 24, 26, 17, 218, 131, 236, 53, 209 };
        private readonly byte[] _mVector = { 146, 64, 191, 111, 23, 3, 113, 119, 231, 121, 25, 21, 112, 79, 32, 114, 156 };


        private readonly ICryptoTransform _mEncryptorTransform;
        private readonly ICryptoTransform _mDecryptorTransform;
        private readonly System.Text.UTF8Encoding _mUtfEncoder;

        public AesCrypt()
        {
            var rm = new RijndaelManaged();

            _mEncryptorTransform = rm.CreateEncryptor(_mKey, _mVector);
            _mDecryptorTransform = rm.CreateDecryptor(_mKey, _mVector);

            _mUtfEncoder = new System.Text.UTF8Encoding();
        }

        static public byte[] GenerateEncryptionKey()
        {
            var rm = new RijndaelManaged();
            rm.GenerateKey();
            return rm.Key;
        }

        static public byte[] GenerateEncryptionVector()
        {
            var rm = new RijndaelManaged();
            rm.GenerateIV();
            return rm.IV;
        }

        public string EncryptToString(string textValue)
        {
            return ByteArrToString(Encrypt(textValue));
        }

        public byte[] Encrypt(string textValue)
        {
            var bytes = _mUtfEncoder.GetBytes(textValue);
            var memoryStream = new MemoryStream();

            var cs = new CryptoStream(memoryStream, _mEncryptorTransform, CryptoStreamMode.Write);
            cs.Write(bytes, 0, bytes.Length);
            cs.FlushFinalBlock();

            memoryStream.Position = 0;
            var encrypted = new byte[memoryStream.Length];
            memoryStream.Read(encrypted, 0, encrypted.Length);

            cs.Close();
            memoryStream.Close();

            return encrypted;
        }

        public string DecryptString(string encryptedString)
        {
            return Decrypt(StrToByteArray(encryptedString));
        }
   
        public string Decrypt(byte[] encryptedValue)
        {
            var encryptedStream = new MemoryStream();
            var decryptStream = new CryptoStream(encryptedStream, _mDecryptorTransform, CryptoStreamMode.Write);
            decryptStream.Write(encryptedValue, 0, encryptedValue.Length);
            decryptStream.FlushFinalBlock();

            encryptedStream.Position = 0;
            var decryptedBytes = new Byte[encryptedStream.Length];
            encryptedStream.Read(decryptedBytes, 0, decryptedBytes.Length);
            encryptedStream.Close();

            return _mUtfEncoder.GetString(decryptedBytes);
        }

        public byte[] StrToByteArray(string str)
        {
            if (str.Length == 0)
                throw new Exception("Invalid string value in StrToByteArray");

            var byteArr = new byte[str.Length / 3];
            var i = 0;
            var j = 0;
            do
            {
                var val = byte.Parse(str.Substring(i, 3));
                byteArr[j++] = val;
                i += 3;
            }
            while (i < str.Length);
            return byteArr;
        }
   
        public string ByteArrToString(byte[] byteArr)
        {
            byte val;
            var tempStr = "";
            for (var i = 0; i <= byteArr.GetUpperBound(0); i++)
            {
                val = byteArr[i];
                if (val < 10)
                    tempStr += string.Format("00{0}", val);
                else if (val < 100)
                    tempStr += string.Format("0{0}", val);
                else
                    tempStr += val.ToString();
            }
            return tempStr;
        }
    }
}
